package com.bigdata.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.bigdata.common.helper.LoginHelper;
import com.bigdata.common.utils.StringUtils;
import com.bigdata.common.core.page.TableDataInfo;
import com.bigdata.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.bigdata.oss.core.OssClient;
import com.bigdata.oss.factory.OssFactory;
import com.bigdata.service.domain.DatasetFiles;
import com.bigdata.service.domain.DatasetTags;
import com.bigdata.service.domain.Tags;
import com.bigdata.service.domain.bo.*;
import com.bigdata.service.domain.vo.*;
import com.bigdata.service.service.*;
import lombok.RequiredArgsConstructor;
import net.sf.jsqlparser.statement.update.UpdateSet;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.stereotype.Service;
import com.bigdata.service.domain.Datasets;
import com.bigdata.service.mapper.DatasetsMapper;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 数据集主Service业务层处理
 *
 * @author ruoyi
 * @date 2025-07-15
 */
@RequiredArgsConstructor
@Service
public class DatasetsServiceImpl implements IDatasetsService {

    private final DatasetsMapper baseMapper;

    private final ITagsService tagsService;

    private final IDatasetTagsService datasetTagsService;

    private final ISearchHistoryService searchHistoryService;

    private final IDatasetFilesService datasetFilesService;

    private final IServiceUsersService serviceUsersService;

    private final IPointTransactionsService pointTransactionsService;

    private final  IPointRulesService pointRulesService;

    private final IUserPointsService userPointsService;

    private final IDataCategoriesService categoryService;


    /**
     * 查询数据集主
     */
    @Override
    public DatasetsVo queryById(String id){
        return baseMapper.selectVoById(id);
    }

    @Override
    public DatasetsVo queryDetailsById(String id) {
        DatasetsVo datasetsVo =  baseMapper.selectVoById(id);


        if(datasetsVo.getDatasetStatus() == 2) {
            Datasets datasetsBo = new Datasets();
            datasetsBo.setId(datasetsVo.getId());
            datasetsBo.setHitsValue(datasetsVo.getHitsValue() + 1);
            this.baseMapper.updateById(datasetsBo);
        }
        List<TagsVo> list = tagsService.queryTagsList(Long.parseLong(id));
        datasetsVo.setTags(list.stream()
            .map(TagsVo::getName)
            .collect(Collectors.toList()));

        DatasetFilesBo filesBo = new DatasetFilesBo();
        filesBo.setDatasetId(id);
        datasetsVo.setCategoryName(categoryService.queryById(datasetsVo.getCategoryId()).getName());
        datasetsVo.setFilesBos(datasetFilesService.queryList(filesBo));
        ServiceUsersVo usersVo = serviceUsersService.queryById(datasetsVo.getCreateUserId());
        usersVo.setPasswordHash("");
        datasetsVo.setPublisher(usersVo);
        return datasetsVo;
    }
    /**
     * 查询数据集主列表
     */
    @Override
    public TableDataInfo<DatasetsVo> queryPageList(DatasetsBo bo, PageQuery pageQuery) {
        if(LoginHelper.getUserId() != null && bo.getTitle() != null) {
            SearchHistoryBo searchHistoryBo = new SearchHistoryBo();
            searchHistoryBo.setUserId(LoginHelper.getUserId());
            searchHistoryBo.setQueryContent(bo.getTitle());
            searchHistoryBo.setSearchTime(DateUtil.date());
            searchHistoryService.insertByBo(searchHistoryBo);
        }

        LambdaQueryWrapper<Datasets> lqw = buildQueryWrapper(bo);
        Page<DatasetsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        TableDataInfo<DatasetsVo> datas = TableDataInfo.build(result);
        datas.getRows().forEach(item -> {
            item.setCategoryName(categoryService.queryById(item.getCategoryId()).getName());
            List<TagsVo> tags = tagsService.queryTagsList(Long.parseLong(item.getId()));
            item.setTags(tags.stream()
                .map(TagsVo::getName)
                .collect(Collectors.toList()));
        });
        return datas;
    }

    /**
     * 查询数据集主列表
     */
    @Override
    public List<DatasetsVo> queryList(DatasetsBo bo) {
        LambdaQueryWrapper<Datasets> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<Datasets> buildQueryWrapper(DatasetsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<Datasets> lqw = Wrappers.lambdaQuery();
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), Datasets::getTitle, bo.getTitle());
        lqw.like(StringUtils.isNotBlank(bo.getSummary()), Datasets::getSummary, bo.getSummary());
        lqw.eq(StringUtils.isNotBlank(bo.getCategoryId()), Datasets::getCategoryId, bo.getCategoryId());
        lqw.eq(StringUtils.isNotBlank(bo.getCoverImagePath()), Datasets::getCoverImagePath, bo.getCoverImagePath());
        lqw.in(bo.getIds() != null, Datasets::getId, bo.getIds());
        lqw.eq(bo.getDataTypeId() != null, Datasets::getDataTypeId, bo.getDataTypeId());
        lqw.eq(bo.getFileSize() != null, Datasets::getFileSize, bo.getFileSize());
        lqw.between(bo.getStartTime()!= null ,Datasets::getCreateTime, bo.getStartTime(), bo.getEndTime());
        lqw.eq(bo.getDatasetStatus() != null, Datasets::getDatasetStatus, bo.getDatasetStatus());
        lqw.eq(bo.getListingStatus() != null, Datasets::getListingStatus, bo.getListingStatus());
        lqw.in(bo.getCategoryIds() != null, Datasets::getCategoryId, bo.getCategoryIds());
        lqw.like(StringUtils.isNotBlank(bo.getCreateBy()), Datasets::getCreateBy, bo.getCreateBy());
        lqw.eq(bo.getCreateUserId() != null, Datasets::getCreateUserId, bo.getCreateUserId());
        if(StringUtils.isNotBlank(bo.getOrderByColumn())) {
//            lqw.orderByDesc(bo.getOrderByColumn());
            if(bo.getOrderByColumn().equals("createTime")) {
                lqw.orderBy(true, bo.getAscValue(), Datasets::getCreateTime);
            }
            if(bo.getOrderByColumn().equals("hitsValue")) {
                lqw.orderBy(true, bo.getAscValue(), Datasets::getHitsValue);
            }
            if(bo.getOrderByColumn().equals("downloadValue")) {
                lqw.orderBy(true, bo.getAscValue(), Datasets::getDownloadValue);
            }

            if(bo.getOrderByColumn().equals("fileSize")) {
                lqw.orderBy(true, bo.getAscValue(), Datasets::getFileSize);
            }

        }else {
            lqw.orderByDesc(bo.getHitsValue() != null, Datasets::getHitsValue);
            lqw.orderByDesc(Datasets::getCreateTime);
        }
        return lqw;
    }


    /**
     * 新增数据集主
     */
    @Override
    public Boolean insertByBo(DatasetsBo bo) {
        Datasets add = BeanUtil.toBean(bo, Datasets.class);
        validEntityBeforeSave(add);
        add.setFileSize(bo.getFilesBos().size());
        add.setCreateUserId(LoginHelper.getUserId());
        add.setCreateByName(LoginHelper.getUsername());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            //插入tags
            insertTags(bo);
            //插入image
            insertImage(bo);
        }
        PointRulesBo rulesBo = new PointRulesBo();
        rulesBo.setActionType("upload");
        List<PointRulesVo>  list = pointRulesService.queryList(rulesBo);
        add.setUploadPointValue(Integer.parseInt(list.get(0).getPointValues().toString()));
        rulesBo.setActionType("download");
        list = pointRulesService.queryList(rulesBo);
        add.setDowPointValue(Integer.parseInt(list.get(0).getPointValues().toString()));
        add.setDatasetStatus(1);
        return flag;
    }

    public void insertImage(DatasetsBo bo) {
//        datasetFilesService.insertByBo()
        List<DatasetFiles> list = new ArrayList<>();
        bo.getFilesBos().forEach(item->{
            DatasetFiles datasetFiles = BeanUtil.toBean(item, DatasetFiles.class);
            datasetFiles.setDatasetId(bo.getId());
            list.add(datasetFiles);
        });
        datasetFilesService.insertBatch(list);
    }
    public void insertTags(DatasetsBo bo) {
        bo.getTags().forEach(tag -> {
            TagsBo tagsBo = new TagsBo();
            tagsBo.setName(tag);
            List<TagsVo> tagsVoList = tagsService.queryList(tagsBo);
            Long id;
            if(tagsVoList.isEmpty()) {
                tagsService.insertByBo(tagsBo);
                id = tagsBo.getId();
            }else {
                id = tagsVoList.get(0).getId();
            }
            //插入tags_datasets
            DatasetTagsBo tags = new DatasetTagsBo();
            tags.setDatasetId(bo.getId());
            tags.setTagId(id);
            datasetTagsService.insertByBo(tags);
        });
    }

    /**
     * 修改数据集主
     */
    @Override
    public Boolean updateByBo(DatasetsBo bo) {
        Datasets update = BeanUtil.toBean(bo, Datasets.class);
        validEntityBeforeSave(update);
        DatasetsVo datasetsVo = queryDetailsById(bo.getId());
        UserPointsVo userPointsVo = userPointsService.queryById(datasetsVo.getCreateUserId());
        if(null == userPointsVo) {
            UserPointsBo userPointsBo = new UserPointsBo();
            userPointsBo.setUserId(datasetsVo.getCreateUserId());
            userPointsBo.setTotalPoints(0L);
            userPointsBo.setCumulativePoints(0L);
            userPointsService.insertByBo(userPointsBo);
            userPointsVo = userPointsService.queryById(datasetsVo.getCreateUserId());

        }

        if(bo.getDatasetStatus() == 1) {
            UserPointsBo userPointsBo = new UserPointsBo();
            userPointsBo.setUserId(datasetsVo.getCreateUserId());
            userPointsBo.setTotalPoints(userPointsVo.getTotalPoints() + bo.getUploadPointValue());
            userPointsBo.setCumulativePoints(userPointsVo.getCumulativePoints() + bo.getUploadPointValue());
            userPointsService.updateByBo(userPointsBo);
        }

        if(bo.getFilesBos().isEmpty()) {

        }

        DatasetsVo batasetsVo = this.queryById(bo.getId());
//        if (!batasetsVo.getTitle().equals(bo.getTitle())) {
//            // 更新 交易表数据
//            PointTransactionsBo transactionsBo = new PointTransactionsBo();
//            transactionsBo.setDatasetId(bo.getId());
//            transactionsBo.setUserId(datasetsVo.getCreateUserId());
//            transactionsBo.setDatasetName(datasetsVo.getTitle());
//            transactionsBo.setPoints(Long.parseLong(bo.getUploadPointValue().toString()));
//            transactionsBo.setTransactionType("decrement");
//            pointTransactionsService.updateByBo(transactionsBo);
//        }
        // 新增下载记录
        PointTransactionsBo transactionsBo = new PointTransactionsBo();
        transactionsBo.setDatasetId(bo.getId());
        transactionsBo.setUserId(datasetsVo.getCreateUserId());
        transactionsBo.setDatasetName(datasetsVo.getTitle());
        transactionsBo.setPoints(Long.parseLong(bo.getUploadPointValue().toString()));
        transactionsBo.setTransactionType("increment");
        transactionsBo.setRemarks(datasetsVo.getCategoryName()+"");
        transactionsBo.setCreateUserId(datasetsVo.getCreateUserId());
        transactionsBo.setCreateUserName(datasetsVo.getCreateByName());
        transactionsBo.setImageUrl(datasetsVo.getCoverImagePath());
        transactionsBo.setCategoryId(Long.parseLong(datasetsVo.getCategoryId()));
        pointTransactionsService.insertByBo(transactionsBo);



        return baseMapper.updateById(update) > 0;
    }


    /**
     * 修改数据集主
     */
    @Override
    public Boolean updateDowByBo(DatasetsBo bo) {
        Datasets update = BeanUtil.toBean(bo, Datasets.class);

        return baseMapper.updateById(update) > 0;
    }
    /**
     * 修改数据集主
     */
    @Override
    public Boolean updateDatasetsByBo(DatasetsBo bo) {
        Datasets update = BeanUtil.toBean(bo, Datasets.class);
        validEntityBeforeSave(update);
        DatasetsVo datasetsVo = queryDetailsById(bo.getId());
        UserPointsVo userPointsVo = userPointsService.queryById(datasetsVo.getCreateUserId());
        UserPointsBo userPointsBo = new UserPointsBo();
        userPointsBo.setUserId(datasetsVo.getCreateUserId());

        if(!bo.getFilesBos().isEmpty()) {
            // 删除文件
            DatasetFilesBo datasetFilesBo = new DatasetFilesBo();
            datasetFilesBo.setDatasetId(bo.getId());
            List<DatasetFilesVo> list = datasetFilesService.queryList(datasetFilesBo);

            // 提取 list2 的所有 ID 集合（用于快速查找）
            List<String> list2Ids = list.stream()
                .map(DatasetFilesVo::getFilePath)
                .collect(Collectors.toList());

            // 找出在 list1 中但不在 list2 中的元素
            List<DatasetFilesBo> differences = bo.getFilesBos().stream()
                .filter(entity -> !list2Ids.contains(entity.getFilePath()))
                .collect(Collectors.toList());
            differences.forEach(item -> {
                OssClient storage = OssFactory.instance("minio");
                storage.delete(item.getFilePath());
            });
            datasetFilesService.deleteByDatasetId(Long.parseLong(bo.getId()));
            insertImage(bo);
        }

        if (!bo.getTags().isEmpty()) {
            this.datasetTagsService.deleteByDatasetId(Long.parseLong(bo.getId()));
            //插入tags
            insertTags(bo);
        }

        return baseMapper.updateById(update) > 0;
    }



    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(Datasets entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除数据集主
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }
    /**
     * 查询数据集主数量
     */
    @Override
    public Long queryCategoriesNum(String id) {
        LambdaQueryWrapper<Datasets> lqw = Wrappers.lambdaQuery();
        lqw.eq(Datasets::getCategoryId, id);
        lqw.eq(Datasets::getDatasetStatus, 1);
        lqw.eq(Datasets::getListingStatus, 1);
        return baseMapper.selectCount(lqw);
    }
}
